﻿#include "mainwindow.h"
#include "ui_mainwindow.h"

#define VIDEO_NAME "/dev/video0"

void Yuv2Rgb(unsigned char* yuv, unsigned char* rgb, int imgWidth, int imgHeight)
{
    unsigned char* y0 = yuv + 0;
    unsigned char* u0 = yuv + 1;
    unsigned char* y1 = yuv + 2;
    unsigned char* v0 = yuv + 3;

    unsigned char* r0 = rgb + 0;
    unsigned char* g0 = rgb + 1;
    unsigned char* b0 = rgb + 2;
    unsigned char* r1 = rgb + 3;
    unsigned char* g1 = rgb + 4;
    unsigned char* b1 = rgb + 5;
    //DBG("yuyv_to_rgb start\n");
    float rt0 = 0, gt0 = 0, bt0 = 0, rt1 = 0, gt1 = 0, bt1 = 0;

    for(int i = 0; i <= (imgWidth * imgHeight) / 2 ;i++)
    {
        bt0 = 1.164 * (*y0 - 16) + 2.018 * (*u0 - 128);
        gt0 = 1.164 * (*y0 - 16) - 0.813 * (*v0 - 128) - 0.394 * (*u0 - 128);
        rt0 = 1.164 * (*y0 - 16) + 1.596 * (*v0 - 128);

        bt1 = 1.164 * (*y1 - 16) + 2.018 * (*u0 - 128);
        gt1 = 1.164 * (*y1 - 16) - 0.813 * (*v0 - 128) - 0.394 * (*u0 - 128);
        rt1 = 1.164 * (*y1 - 16) + 1.596 * (*v0 - 128);

        if(rt0 > 250)  	rt0 = 255;
        if(rt0 < 0)    	rt0 = 0;

        if(gt0 > 250) 	gt0 = 255;
        if(gt0 < 0)	gt0 = 0;

        if(bt0 > 250)	bt0 = 255;
        if(bt0 < 0)	bt0 = 0;

        if(rt1 > 250)	rt1 = 255;
        if(rt1 < 0)	rt1 = 0;

        if(gt1 > 250)	gt1 = 255;
        if(gt1 < 0)	gt1 = 0;

        if(bt1 > 250)	bt1 = 255;
        if(bt1 < 0)	bt1 = 0;

        *r0 = (unsigned char)bt0;
        *g0 = (unsigned char)gt0;
        *b0 = (unsigned char)rt0;

        *r1 = (unsigned char)bt1;
        *g1 = (unsigned char)gt1;
        *b1 = (unsigned char)rt1;

        yuv = yuv + 4;
        rgb = rgb + 6;
        if(yuv == NULL)
          break;

        y0 = yuv;
        u0 = yuv + 1;
        y1 = yuv + 2;
        v0 = yuv + 3;

        r0 = rgb + 0;
        g0 = rgb + 1;
        b0 = rgb + 2;
        r1 = rgb + 3;
        g1 = rgb + 4;
        b1 = rgb + 5;
    }
}

void MainWindow::showImg(QPixmap &img)
{
    QPixmap ScaPic = img.scaled(ui->CameraDisplay->size());
    ui->CameraDisplay->setPixmap(ScaPic);
}

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    int Ret = -1;
    ui->setupUi(this);
    this->move(0, 0);
    ui->CameraOp->setText(tr("开启摄像头"));
    ui->MoniterState->setText(tr("摄像头已关闭"));
    qRegisterMetaType<QPixmap>("QPixmap&");
    qRegisterMetaType<unsigned char *>("unsigned char *");
    CameraInfo.DevName = VIDEO_NAME;
    CameraInfo.Format = V4L2_PIX_FMT_YUYV;
    CameraInfo.Width = CAMERA_WIDTH;
    CameraInfo.Height = CAMERA_HEIGHT;
    Ret = UsbCameraOpen(&CameraInfo);
    if(Ret < 0)
    {
        qDebug() << "UsbCameraOpen failed!";
        return;
    }
    UsbCameraSetContrast(40);
    UsbCameraSetSharpness(16);
    UsbCameraSetBrightness(10);
    UsbCameraSetSharpness(7);
    UsbCameraSetSaturation(13);
    UsbCameraSetHue(0);
    ui->brightness_ctl->setValue(10);
    ui->contrast_ctl->setValue(40);
    ui->sharpness_ctl->setValue(7);
    ui->saturation_ctl->setValue(13);
    ui->hue_ctl->setValue(0);
    pthread_create(&CameraThread, NULL, CameraThreadHandler, (void *)this);
    pthread_detach(CameraThread);
    connect(this, SIGNAL(sendRawData(unsigned char *)), this, SLOT(handleRawData(unsigned char *)));
    connect(this, SIGNAL(CameraIsStop()), this, SLOT(CameraIsStopHandler()));
}

void MainWindow::handleRawData(unsigned char *Data)
{
    QImage img;
    img = QImage(Data, CAMERA_WIDTH, CAMERA_HEIGHT, QImage::Format_RGB888);
    QPixmap pix = QPixmap::fromImage(img);
    this->showImg(pix);
}

void MainWindow::CameraIsStopHandler()
{
    ui->CameraOp->setText(tr("开启摄像头"));
    ui->MoniterState->setText(tr("摄像头已关闭"));
    ui->CameraDisplay->clear();
    ui->CameraDisplay->setStyleSheet(QStringLiteral("background-color: rgb(0, 0, 0);"));
}

void *MainWindow::CameraThreadHandler(void *arg)
{
    struct buffer Buf;
    unsigned char DispBuf[CAMERA_WIDTH * CAMERA_HEIGHT * 3] = {0};
    MainWindow *Ptr = (MainWindow*)arg;
    for(;;)
    {
        switch(Ptr->StateMachine)
        {
        case CAMERA_IDLE:
            usleep(20*1000);
            break;

        case CAMEAR_STOP:
            UsbCameraStopCapture();
            Ptr->StateMachine = CAMERA_IDLE;
            emit Ptr->CameraIsStop();
            qDebug() << "CAMEAR_STOP";
            break;

        case CAMERA_START:
            UsbCameraStartCapture();
            Ptr->StateMachine = CAMERA_STREAM;
            qDebug() << "CAMERA_START";
            break;

        case CAMERA_STREAM:
            Buf = UsbCameraGetRawData();
            Yuv2Rgb((unsigned char *)Buf.start, DispBuf, CAMERA_WIDTH, CAMERA_HEIGHT);
            emit Ptr->sendRawData(DispBuf);
            break;
        }
    }
    return NULL;
}

void MainWindow::on_CameraOp_released()
{
    switch(CameraState)
    {
    case 0:
        CameraState = 1;
        this->StateMachine = CAMERA_START;
        ui->CameraOp->setText(tr("关闭摄像头"));
        ui->MoniterState->setText(tr("摄像头已开启"));
        break;
    case 1:
        CameraState = 0;
        this->StateMachine = CAMEAR_STOP;
        break;
    }
}

MainWindow::~MainWindow()
{
    delete ui;
}

void Sleep(int msec)
{
    QTime dieTime = QTime::currentTime().addMSecs(msec);
    while( QTime::currentTime() < dieTime )
        QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}

void MainWindow::on_brightness_ctl_valueChanged(int value)
{
    UsbCameraSetBrightness(value);
    ui->brightness->setText(QString("调节亮度:%1").arg(value));
}

void MainWindow::on_contrast_ctl_valueChanged(int value)
{
    UsbCameraSetContrast(value);
    ui->contrast->setText(QString("调节对比度:%1").arg(value));
}

void MainWindow::on_sharpness_ctl_valueChanged(int value)
{
    UsbCameraSetSharpness(value);
    ui->sharpness->setText(QString("调节清晰度:%1").arg(value));
}

void MainWindow::on_saturation_ctl_valueChanged(int value)
{
    UsbCameraSetSaturation(value);
    ui->saturation->setText(QString("调节饱和度:%1").arg(value));
}

void MainWindow::on_hue_ctl_valueChanged(int value)
{
    UsbCameraSetHue(value);
    ui->hue->setText(QString("调节色调:%1").arg(value));
}
